﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gen_SMR
{
    public void Update()
    {
        Vector3[] vs;
        UpdateData(out vs);
        mesh.vertices = vs;
        mesh.RecalculateNormals();
    }
    void UpdateData(out Vector3[] vs)
    {
        vs = new Vector3[mesh.vertexCount];
        Vector3 v;
        for (int i = 0; i < mesh.vertexCount; i++)
        {
            var bi = boneWgts[i];
            v = Vector3.zero;
            foreach (Weight bone in bi.wgts)
            {
                v += bone.t.TransformPoint(bone.delta) * bone.weight;
            }
            vs[i] = v;
        }
    }
    public Gen_SMR(Transform transform, Transform[] bones, Mesh mesh,
        Transform rig, Material material, List<BoneWeights> boneWgts)
    {
        this.transform = transform;
        this.bones = bones;
        this.mesh = mesh;
        this.rig = rig;
        this.material = material;
        this.boneWgts = boneWgts;
    }
    public List<BoneWeights> boneWgts;
    public Transform transform;
    public Transform[] bones;
    public Mesh mesh;
    public Transform rig;
    public Material material;
    int GetBoneIdx(Transform t)
    {
        //if (t == null) return 0; // 目前的机制通常不会出现受影响骨骼数少于4的情况。
        // 总骨骼数少于4应该会出现，留个TODO
        for (int i = 0; i < bones.Length; i++)
        {
            if (bones[i] == t) return i;
        }
        throw new System.Exception("UnMatch Bone");
    }
    public void GenerateSMR()
    {
        var vCount = boneWgts.Count;
        var weights = new BoneWeight[vCount];
        for (int v = 0; v < vCount; v++)
        {
            var bw = boneWgts[v];
            weights[v].boneIndex0 = GetBoneIdx(bw.wgts[0].t);
            weights[v].weight0 = bw.wgts[0].weight;

            weights[v].boneIndex1 = GetBoneIdx(bw.wgts[1].t);
            weights[v].weight1 = bw.wgts[1].weight;

            // 机制的最低骨骼数是2根

            if (bw.wgts.Count > 2 && bw.wgts[2] != null)
            {
                weights[v].boneIndex2 = GetBoneIdx(bw.wgts[2].t);
                weights[v].weight2 = bw.wgts[2].weight;
            }
            if (bw.wgts.Count > 3 && bw.wgts[3] != null)
            {
                weights[v].boneIndex3 = GetBoneIdx(bw.wgts[3].t);
                weights[v].weight3 = bw.wgts[3].weight;
            }
        }
        var bindPoses = new Matrix4x4[bones.Length];
        for (int i = 0; i < bones.Length; i++)
        {
            bindPoses[i] = bones[i].worldToLocalMatrix * transform.localToWorldMatrix;
        }
        mesh.bindposes = bindPoses;
        mesh.boneWeights = weights;
        var smr = transform.GetComOrAdd<SkinnedMeshRenderer>();
        smr.sharedMaterial = material;
        smr.bones = bones;
        smr.rootBone = rig;
        smr.sharedMesh = mesh;
        //使用副法线为切线
        mesh.RecalculateTangents();
        smr.UseBinormalAsTangent();

        try
        {
            var mc = transform.GetComOrAdd<MeshCollider>();
            mc.sharedMesh = mesh;
        }
        catch { Debug.LogError("MeshCol Error"); }
    }
}
